/**
 * Repository辅助工具
 * 统一缓存逻辑，减少重复代码，实现批量查询优化
 */

import { globalCache } from '../cache/SimpleCache';

/**
 * Repository辅助工具类
 */
export class RepositoryHelper {
    /**
     * 带缓存的数据获取
     * 统一缓存逻辑，避免每个Repository都写重复代码
     */
    static async withCache<T>(
        cacheKey: string,
        dataLoader: () => Promise<T>,
        ttl: number = 300000 // 默认5分钟
    ): Promise<T> {
        // 先检查缓存
        const cached = globalCache.get<T>(cacheKey);
        if (cached !== null) {
            return cached;
        }
        
        try {
            // 加载数据
            const data = await dataLoader();
            
            // 缓存数据（只缓存有效数据）
            if (data !== null && data !== undefined) {
                globalCache.set(cacheKey, data, ttl);
            }
            
            return data;
        } catch (error) {
            // 数据加载失败时，不缓存错误，直接抛出
            throw error;
        }
    }

    /**
     * 批量获取数据，自动优化查询
     * 先从缓存获取，只查询缓存中没有的数据
     */
    static async batchGet<T>(
        ids: string[],
        keyPrefix: string,
        batchLoader: (uncachedIds: string[]) => Promise<Map<string, T>>,
        ttl: number = 300000
    ): Promise<Map<string, T>> {
        const result = new Map<string, T>();
        const uncachedIds: string[] = [];
        
        // 检查缓存，收集未缓存的ID
        for (const id of ids) {
            const cached = globalCache.get<T>(`${keyPrefix}:${id}`);
            if (cached !== null) {
                result.set(id, cached);
            } else {
                uncachedIds.push(id);
            }
        }
        
        // 如果有未缓存的数据，批量加载
        if (uncachedIds.length > 0) {
            try {
                const loadedData = await batchLoader(uncachedIds);
                
                // 缓存新加载的数据并添加到结果中
                for (const [id, data] of loadedData) {
                    globalCache.set(`${keyPrefix}:${id}`, data, ttl);
                    result.set(id, data);
                }
            } catch (error) {
                console.warn(`Batch loading failed for prefix ${keyPrefix}:`, error);
                // 批量加载失败，但已缓存的数据仍然有效
            }
        }
        
        return result;
    }

    /**
     * 批量获取并保持顺序
     * 返回数组，与输入ID顺序一致
     */
    static async batchGetOrdered<T>(
        ids: string[],
        keyPrefix: string,
        batchLoader: (uncachedIds: string[]) => Promise<Map<string, T>>,
        ttl: number = 300000
    ): Promise<(T | null)[]> {
        const dataMap = await this.batchGet(ids, keyPrefix, batchLoader, ttl);
        return ids.map(id => dataMap.get(id) || null);
    }

    /**
     * 缓存失效
     * 删除指定key的缓存
     */
    static invalidateCache(cacheKey: string): boolean {
        return globalCache.delete(cacheKey);
    }

    /**
     * 批量缓存失效
     * 按前缀删除缓存
     */
    static invalidateCacheByPrefix(prefix: string): number {
        return globalCache.clearByPrefix(prefix);
    }

    /**
     * 预热缓存
     * 提前加载数据到缓存中
     */
    static async warmupCache<T>(
        cacheKey: string,
        dataLoader: () => Promise<T>,
        ttl: number = 300000
    ): Promise<void> {
        try {
            const data = await dataLoader();
            if (data !== null && data !== undefined) {
                globalCache.set(cacheKey, data, ttl);
            }
        } catch (error) {
            console.warn(`Cache warmup failed for key ${cacheKey}:`, error);
        }
    }

    /**
     * 条件缓存
     * 只有满足条件时才缓存数据
     */
    static async conditionalCache<T>(
        cacheKey: string,
        dataLoader: () => Promise<T>,
        shouldCache: (data: T) => boolean,
        ttl: number = 300000
    ): Promise<T> {
        // 先检查缓存
        const cached = globalCache.get<T>(cacheKey);
        if (cached !== null) {
            return cached;
        }
        
        // 加载数据
        const data = await dataLoader();
        
        // 条件缓存
        if (shouldCache(data)) {
            globalCache.set(cacheKey, data, ttl);
        }
        
        return data;
    }

    /**
     * 刷新缓存
     * 强制重新加载数据并更新缓存
     */
    static async refreshCache<T>(
        cacheKey: string,
        dataLoader: () => Promise<T>,
        ttl: number = 300000
    ): Promise<T> {
        // 先删除旧缓存
        globalCache.delete(cacheKey);
        
        // 重新加载并缓存
        const data = await dataLoader();
        if (data !== null && data !== undefined) {
            globalCache.set(cacheKey, data, ttl);
        }
        
        return data;
    }

    /**
     * 获取或创建
     * 如果缓存中没有数据，创建默认数据并缓存
     */
    static async getOrCreate<T>(
        cacheKey: string,
        dataLoader: () => Promise<T | null>,
        defaultCreator: () => Promise<T>,
        ttl: number = 300000
    ): Promise<T> {
        // 先检查缓存
        const cached = globalCache.get<T>(cacheKey);
        if (cached !== null) {
            return cached;
        }
        
        // 尝试加载数据
        let data = await dataLoader();
        
        // 如果没有数据，创建默认数据
        if (data === null) {
            data = await defaultCreator();
        }
        
        // 缓存数据
        globalCache.set(cacheKey, data, ttl);
        
        return data;
    }

    /**
     * 分页缓存
     * 为分页查询提供缓存支持
     */
    static async cachedPageQuery<T>(
        baseKey: string,
        page: number,
        pageSize: number,
        queryParams: any,
        dataLoader: () => Promise<{ data: T[]; total: number }>,
        ttl: number = 60000 // 分页查询缓存时间较短，默认1分钟
    ): Promise<{ data: T[]; total: number }> {
        // 生成包含查询参数的缓存key
        const paramsHash = this.hashObject(queryParams);
        const cacheKey = `${baseKey}:page:${page}:${pageSize}:${paramsHash}`;
        
        return this.withCache(cacheKey, dataLoader, ttl);
    }

    /**
     * 对象哈希
     * 为对象生成简单的哈希值，用于缓存key
     */
    private static hashObject(obj: any): string {
        const str = JSON.stringify(obj, Object.keys(obj).sort());
        let hash = 0;
        for (let i = 0; i < str.length; i++) {
            const char = str.charCodeAt(i);
            hash = ((hash << 5) - hash) + char;
            hash = hash & hash; // Convert to 32bit integer
        }
        return hash.toString(36);
    }

    /**
     * 获取缓存统计信息
     */
    static getCacheStats() {
        return globalCache.getStats();
    }

    /**
     * 构建缓存key
     * 提供统一的缓存key构建方法
     */
    static buildCacheKey(prefix: string, ...parts: (string | number)[]): string {
        return [prefix, ...parts].join(':');
    }

    /**
     * 验证必需参数
     * 简单的参数验证工具
     */
    static validateRequiredParams(params: any, requiredFields: string[]): void {
        const missing = requiredFields.filter(field => 
            params[field] === undefined || params[field] === null || params[field] === ''
        );
        
        if (missing.length > 0) {
            throw new Error(`Missing required parameters: ${missing.join(', ')}`);
        }
    }
}
